<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * This file contains some helper functions for generating HTTP headers and
 * redirecting clients. The following functions are defined:
 *
 * - redirect
 * - get_http_header
 * - get_http_header_desc
 * - status_header
 * - nocache_headers
 *
 * PHP version 5
 *
 * This file is part of Majic - A rapid-development web application framework
 * for PHP 5.
 *
 * Majic is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * Majic is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Majic. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package     Majic
 * @author      Michael J. I. Jackson <mjijackson@gmail.com>
 * @copyright   2007-2008 Michael J. I. Jackson
 * @license     http://www.gnu.org/licenses/lgpl-3.0.txt GNU LGPL 3.0
 * @version     SVN: $Id: http.php 41 2008-08-30 16:11:11Z mjijackson $
 */

use_helper('url'); // for redirect()'s link_to()

/**
 * Gets the text for an HTTP header with the given status code using the current
 * server protocol.
 *
 * @param   int         $status     The HTTP status code
 * @return  string                  The HTTP header text
 * @throws  Exception               If the given status code is unknown
 */
function get_http_header($status)
{
    $desc = get_http_header_desc($status);
    if ($desc == '') {
        throw new Exception("Unknown HTTP status: $status");
    }

    if (isset($_SERVER['SERVER_PROTOCOL'])) {
        $protocol = $_SERVER['SERVER_PROTOCOL'];
    } else {
        $protocol = 'HTTP/1.1';
    }

    return "$protocol $status $desc";
}

/**
 * Gets the short description for an HTTP status header.
 *
 * @param   int     $status     The HTTP status code
 * @return  string              A short description for the status code
 */
function get_http_header_desc($status)
{
    $status = (int) $status;
    static $header_desc;

    if (!isset($header_desc)) {
        $header_desc = array(
            100 => 'Continue',
            101 => 'Switching Protocols',

            200 => 'OK',
            201 => 'Created',
            202 => 'Accepted',
            203 => 'Non-Authoritative Information',
            204 => 'No Content',
            205 => 'Reset Content',
            206 => 'Partial Content',

            300 => 'Multiple Choices',
            301 => 'Moved Permanently',
            302 => 'Found',
            303 => 'See Other',
            304 => 'Not Modified',
            305 => 'Use Proxy',
            307 => 'Temporary Redirect',

            400 => 'Bad Request',
            401 => 'Unauthorized',
            403 => 'Forbidden',
            404 => 'Not Found',
            405 => 'Method Not Allowed',
            406 => 'Not Acceptable',
            407 => 'Proxy Authentication Required',
            408 => 'Request Timeout',
            409 => 'Conflict',
            410 => 'Gone',
            411 => 'Length Required',
            412 => 'Precondition Failed',
            413 => 'Request Entity Too Large',
            414 => 'Request-URI Too Long',
            415 => 'Unsupported Media Type',
            416 => 'Requested Range Not Satisfiable',
            417 => 'Expectation Failed',

            500 => 'Internal Server Error',
            501 => 'Not Implemented',
            502 => 'Bad Gateway',
            503 => 'Service Unavailable',
            504 => 'Gateway Timeout',
            505 => 'HTTP Version Not Supported'
        );
    }

    return isset($header_desc[$status]) ? $header_desc[$status] : '';
}

/**
 * Sends a redirect header to the client. The $method parameter may be any HTTP
 * redirect status code (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3)
 * to use an HTTP redirect or 'refresh' to use the refresh header method.
 *
 * @param   string  $page       The page to redirect the client to
 * @param   mixed   $method     (optional) The redirect method to use, defaults
 *                              to 302
 * @return  void
 */
function redirect($page, $method = 302)
{
    if (strpos($page, '://') === false) {
        $page = link_to($page, true);
    }

    if (strtolower($method) == 'refresh') {
        header("Refresh: 0; url=$page");
    } else {
        if (!is_numeric($method) || $method < 300 || $method > 307) {
            $method = 302;
        }

        status_header($method);
        header("Location: $page", true);
    }

    exit(0);
}

/**
 * Sends an HTTP status header to the client using the given status code.
 *
 * @param   int     $status     The HTTP status to use
 * @return  void
 */
function status_header($status)
{
    $header = get_http_header($status);
    header($header, true, $status);
}

/**
 * Sends special headers to the client to prevent page caching.
 *
 * @return  void
 */
function nocache_headers()
{
    header('Expires: Wed, 11 Jan 1984 05:00:00 GMT');
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
    header('Cache-Control: no-cache, must-revalidate, max-age=0');
    header('Pragma: no-cache');
}

?>
